﻿using System.Data;
using System.Runtime.Serialization;

namespace AppGene.DataModel
{
    /// <summary>
    /// The class provides a description of a logical column.
    /// </summary>
    [DataContract]
    public class LogicalColumn : IExtensibleDataObject
    {
        /// <summary>
        /// Create a logical column instance.
        /// <param name="name">The column name.</param>
        /// <param name="nativeDataType">The native data type</param>
        /// </summary>
        internal LogicalColumn(string name, string nativeDataType)
            : this(name, null, null)
        {
            this.NativeDataType = nativeDataType;
        }

        /// <summary>
        /// Create a logical column instance.
        /// <param name="name">The column name.</param>
        /// <param name="dataType">The logical data type</param>
        /// </summary>
        internal LogicalColumn(string name,
            DbType dataType)
            : this(name, dataType, LogicalDataTypeInfo.GetDataTypeAttribute(dataType))
        { }

        /// <summary>
        /// Create a logical column instance.
        /// <param name="name">The column name.</param>
        /// <param name="dataType">The logical data type.</param>
        /// <param name="length">The length of the column.</param>
        /// </summary>
        internal LogicalColumn(string name,
            DbType dataType,
            int length)
            : this(name, dataType, LogicalDataTypeInfo.GetDataTypeAttribute(dataType))
        {
            this.Length = length;
        }

        /// <summary>
        /// Create a logical column instance.
        /// <param name="name">The column name.</param>
        /// <param name="dataType">The logical data type</param>
        /// <param name="precision">The precision of the column.</param>
        /// <param name="scale">The scale of the column.</param>
        /// </summary>
        internal LogicalColumn(string name,
            DbType dataType,
            int precision,
            int scale)
            : this(name, dataType, LogicalDataTypeInfo.GetDataTypeAttribute(dataType))
        {
            this.Precision = precision;
            this.Scale = scale;
        }

        /// <summary>
        /// Create a logical column instance.
        /// <param name="name">The column name.</param>
        /// <param name="dataType">The logical data type.</param>
        /// <param name="dataTypeAttribute">The logical data type's attributes.</param>
        /// </summary>
        private LogicalColumn(string name,
            DbType? dataType,
            LogicalDataTypeInfo dataTypeAttribute)
        {
            this.Name = name;
            this.dataType = dataType;
            if (dataType.HasValue)
            {
                this.AllowNull = dataTypeAttribute.AllowNull;
                this.DefaultValue = dataTypeAttribute.DefaultValue;
                if (dataTypeAttribute.DefaultLength >= 0)
                {
                    this.Length = dataTypeAttribute.DefaultLength;
                }
            }
        }

        #region IExtensibleDataObject Implementation
        private ExtensionDataObject extensionData_Value;
        private DbType? dataType;

        ExtensionDataObject IExtensibleDataObject.ExtensionData
        {
            get
            {
                return extensionData_Value;
            }
            set
            {
                extensionData_Value = value;
            }
        }
        #endregion

        /// <summary>
        /// The table the column belongs to.
        /// </summary>
        public LogicalTable Table { get; internal set; }

        /// <summary>
        /// Indicates if allow null value in the column.
        /// </summary>
        [DataMember]
        public bool AllowNull { get; set; }

        /// <summary>
        /// The data type of the column.
        /// </summary>
        [DataMember]
        public DbType LogicalDataType { get; set; }

        /// <summary>
        /// The native data type of the column.
        /// </summary>
        [DataMember]
        public string NativeDataType { get; set; }

        /// <summary>
        /// The length of the column.
        /// </summary>
        [DataMember]
        public int Length { get; set; }

        /// <summary>
        /// The column options. Any options will be added at the end of column definition.
        /// </summary>
        [DataMember]
        public string Options { get; set; }

        /// <summary>
        /// The precision of the column.
        /// </summary>
        [DataMember]
        public int Precision { get; set; }

        /// <summary>
        /// The scale of the column.
        /// </summary>
        [DataMember]
        public int Scale { get; set; }

        /// <summary>
        /// The default value of the column.
        /// </summary>
        [DataMember]
        public object DefaultValue { get; set; }

        /// <summary>
        /// The description of the column.
        /// </summary>
        [DataMember]
        public string Description { get; set; }

        /// <summary>
        /// Identity increment.
        /// </summary>
        [DataMember]
        public int IdentityIncrement { get; set; }

        /// <summary>
        /// Identity seed
        /// </summary>
        [DataMember]
        public int IdentitySeed { get; set; }

        private bool isIdentity = false;
        /// <summary>
        /// Is Identity
        /// </summary>
        [DataMember]
        public bool IsIdentity
        {
            get
            {
                return isIdentity;
            }
            set
            {
                isIdentity = value;
                if (isIdentity)
                {
                    this.IdentitySeed = 1;
                    this.IdentityIncrement = 1;
                }
                else
                {
                    this.IdentitySeed = 0;
                    this.IdentityIncrement = 0;
                }
            }
        }

        /// <summary>
        /// The label of the column.
        /// </summary>
        [DataMember]
        public string Label { get; set; }

        /// <summary>
        /// The name of the column.
        /// </summary>
        [DataMember]
        public string Name { get; private set; }
    }
}
